#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "pthread.h"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "myglutaux.h"
#include "AWLVP_DistanceMatrix.h"
#include "AWLocalViewport.h"
#include "FTGLPolygonFont.h"
#include "AWLocalViewport.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWBody.h"
#include "AWMsgMoveBody.h"
#include "AWNOOSCBBody.h"

#include "AWLocalViewport.h"
#include "AWLVP_NOOSMain.h"
#include "AWLVP_NOOSOntology.h"

#include "loader.h"

extern int SCREEN_DX,SCREEN_DY;


AW_NOOSCBBody::AW_NOOSCBBody(Ontology *O,FTKBase *Memory,FTKBase *CB) : AW_MsgMoveBody(O,Memory) 
{
	class_name->set("AW_NOOSCBBody");

	operators();

	m_casebase=CB;

	body_r=0.6F;
	body_g=0.6F;
	body_b=0.6F;
	text_status=new Symbol("");

	font=0;

	m_ontology_viewport=new AW_LVP_NOOSOntology(32,SCREEN_DY*0.42F,SCREEN_DX*0.33F,SCREEN_DY*0.58F-32,m_ontology,m_casebase);

	m_local_viewports.Add(new AW_LVP_NOOSMain(16,16,SCREEN_DX-32,SCREEN_DY-32,m_casebase,m_memory,m_ontology_viewport,&m_local_viewports));
	m_local_viewports.Add(m_ontology_viewport);

} /* AW_NOOSCBBody::AW_NOOSCBBody */ 


AW_NOOSCBBody::AW_NOOSCBBody(FILE *fp,Ontology *O,FTKBase *Memory,FTKBase *CB) : AW_MsgMoveBody(O,Memory) 
{
	class_name->set("AW_NOOSCBBody");

	operators();

	m_casebase=CB;

	body_r=0.6F;
	body_g=0.6F;
	body_b=0.6F;
	text_status=new Symbol("");

	font=0;

	m_ontology_viewport=new AW_LVP_NOOSOntology(32,SCREEN_DY*0.42F,SCREEN_DX*0.33F,SCREEN_DY*0.58F-32,m_ontology,m_casebase);

	m_local_viewports.Add(new AW_LVP_NOOSMain(16,16,SCREEN_DX-32,SCREEN_DY-32,m_casebase,m_memory,m_ontology_viewport,&m_local_viewports));
	m_local_viewports.Add(m_ontology_viewport);

	load(fp);
} /* AW_NOOSCBBody::AW_NOOSCBBody */ 



void AW_NOOSCBBody::operators(void)
{
	FeatureTerm *op;

	m_ontology->new_sort("color-operator","any",3,"r","float","g","float","b","float");
	op=FeatureTerm::fromStringNOOS("(define (color-operator))",m_memory,m_ontology);
	op->defineFeatureValue("r",new FeatureTerm((Symbol *)0,m_ontology->get_sort("float"),0));
	op->defineFeatureValue("g",new FeatureTerm((Symbol *)0,m_ontology->get_sort("float"),0));
	op->defineFeatureValue("b",new FeatureTerm((Symbol *)0,m_ontology->get_sort("float"),0));
	m_ops.Add(op);

	m_ontology->new_sort("status-operator","any",1,"text","symbol");
	op=FeatureTerm::fromStringNOOS("(define (status-operator))",m_memory,m_ontology);
	op->defineFeatureValue("text",new FeatureTerm((Symbol *)0,m_ontology->get_sort("symbol"),0));
	m_ops.Add(op);
} /* AW_NOOSCBBody::operators */ 


AW_NOOSCBBody::~AW_NOOSCBBody()
{
	m_ontology_viewport=0;

	// I don't know why, but the memory_manager complains about this free:
	if (font!=0) {
//		delete font;
		font=0;
	} /* if */ 

} /* AW_NOOSCBBody::~AW_NOOSCBBody */ 


bool AW_NOOSCBBody::load(FILE *fp) 
{
	float t1,t2,t3;

	if (!AW_MsgMoveBody::load(fp)) return false;

	if (3!=fscanf(fp,"%f %f %f",&t1,&t2,&t3)) return false;
	body_r=t1;
	body_g=t2;
	body_b=t3;
	if (text_status!=0) delete text_status;
	text_status = new Symbol(fp);

	return true;
} /* AW_NOOSCBBody::load */ 


bool AW_NOOSCBBody::save(FILE *fp) 
{
	if (!AW_MsgMoveBody::save(fp)) return false;

	fprintf(fp,"%f %f %f\n",float(body_r),float(body_g),float(body_b));
	text_status->save(fp);

	return true;
} /* AW_NOOSCBBody::save */ 


bool AW_NOOSCBBody::is_a(char *c)
{
	if (strcmp(c,"AW_NOOSCBBody")==0) return true;

	return AW_MsgMoveBody::is_a(c);
} /* AW_NOOSCBBody::is_a */ 


bool AW_NOOSCBBody::is_a(Symbol *c)
{
	if (c->cmp("AW_NOOSCBBody")) return true;

	return AW_MsgMoveBody::is_a(c);
} /* AW_NOOSCBBody::is_a */ 


bool AW_NOOSCBBody::ApplyOperator(FeatureTerm *op,float time,AW_Agent *a,AW_World *w)
{
/*
	{
		char *s;
		s=op->toStringNOOS(m_memory);
		write_debug_report("[AW_MsgMoveBody]: applying operator: %s\n",s);
		delete []s;
	}
*/

	if (strcmp(op->getSort()->get(),"color-operator")==0) {
		body_r=op->featureValueQuick("r")->getFloat();
		body_g=op->featureValueQuick("g")->getFloat();
		body_b=op->featureValueQuick("b")->getFloat();
		return true;
	} /* if */ 

	if (strcmp(op->getSort()->get(),"status-operator")==0) {
		if (text_status!=0) delete text_status;
		text_status=new Symbol(op->featureValueQuick("text")->getSymbol());
		return true;
	} /* if */ 

	return AW_MsgMoveBody::ApplyOperator(op,time,a,w);
} /* AW_NOOSCBBody::ApplyOperator */ 


void AW_NOOSCBBody::draw_body(void)
{

	if (font==0) {
		FILE *fp=fopen("arial.ttf","r");
		if (fp!=0) {
			fclose(fp);
			font=new FTGLPolygonFont("arial.ttf");
			font->FaceSize(2);
			font->Depth(0.2F);
		} /* if */ 
	} /* if */  

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

	// Body:
	glTranslatef(0.0F,-1.0F,0.0F);
	glColor3f(body_r,body_g,body_b);
	glutSolidSphere(1.0,16,16);

	glColor3f(0.5,0.0,0.0);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(0.2F,-0.4F,0.8F);
	glutSolidSphere(0.2,16,16);
	glPopMatrix();
	glPushMatrix();
	glTranslatef(-0.2F,-0.4F,0.8F);
	glutSolidSphere(0.2,16,16);
	glPopMatrix();

	// Case Base:
	{
		GLUquadric *q;

		q=gluNewQuadric();

		glTranslatef(2.2F,1.0,0);
		glColor3f(0,0,1);
		glPushMatrix();
		glRotatef(90,1,0,0);
		gluCylinder(q,1.0,1.0,2.0,16,2);
		glPopMatrix();

		glTranslatef(0.0F,-2.0,0);
		glRotatef(90,1,0,0);
		gluDisk( q, 0.0, 1.0, 16, 1);
	 
        gluDeleteQuadric(q);

		// Case Base Size:
		if (font!=0) {
			char str[80];
			float llx,lly,llz,urx,ury,urz;

			glPushMatrix();
			glTranslatef(0,1.2f,-0.75f);
			glNormal3f(0,0,1);
			glRotatef(180,0,0,1);
			glRotatef(90,1,0,0);
			glScalef(0.33F,0.33F,0.33F);			

			sprintf(str,"%i",m_casebase->get_n_terms());

			font->BBox( str, llx, lly, llz, urx, ury, urz);		
			glTranslatef(-(urx-llx)/2,-(ury-lly)/2,-(urz-llz)/2);
			glColor3f(1,1,1);
			font->Render(str);
			glPopMatrix();
		} /* if */ 
	}

	// Status Message:
	if (font!=0) {
		char str[80];
		float llx,lly,llz,urx,ury,urz;

		glPushMatrix();
		glTranslatef(-1,0,1.5f);
		glNormal3f(0,0,1);
		glRotatef(180,0,0,1);
		glRotatef(90,1,0,0);
		glScalef(0.33F,0.33F,0.33F);			

		sprintf(str,"%s",text_status->get());

		font->BBox( str, llx, lly, llz, urx, ury, urz);		
		glTranslatef(-(urx-llx)/2,-(ury-lly)/2,-(urz-llz)/2);
		glColor3f(1,1,1);
		font->Render(str);
		glPopMatrix();
	} /* if */ 


	glPopMatrix();

} /* AW_NOOSCBBody::draw_body */ 

